#pragma once

#include <unordered_map>
#include <functional>
#include <mutex>
#include "Package.h"

namespace wsbus {

	using ReplyMessage = std::function<int(const PackagePtr &reqPackage, const MoreMessagePtr &rspMsg)>;
	using HandleMessage = std::function<void(int, const PackagePtr&)>;

	class MessageHandler
	{
	public:
		virtual ~MessageHandler() {}
		virtual int type() const = 0;
		virtual void onHandle(const PackagePtr &msg) = 0;
	};

	class ResponseHandler : public MessageHandler
	{
	public:
		struct Info {
			PackagePtr requestMessage;
			HandleMessage responseCallback;
			time_t requestTime{ 0 };
			time_t responseTime{ 0 };
			int msTimeout{ 0 };
		};

		int type() const { return PacHeader::eRsp; }
		void onHandle(const PackagePtr &msg) override;

		void put(const PackagePtr &msg, const HandleMessage &cb, int msTimeout);
		bool pick(int msgid, Info &info);

	private:
		std::mutex mutex_;
		std::unordered_map<int, Info> cache_;
	};

	class RequestHandler : public MessageHandler
	{
	public:
		RequestHandler(const ReplyMessage &reply);
		int type() const { return PacHeader::eReq; }
		void onHandle(const PackagePtr &msg) override;
		void addHandle(const std::string &cmd, const std::function<MoreMessagePtr(const PackagePtr&)> &cb);

	private:
		ReplyMessage reply_;
		std::unordered_map<std::string, std::function<MoreMessagePtr(const PackagePtr&)>> data_;
	};

	class PublishHandler : public MessageHandler
	{
	public:
		int type() const { return PacHeader::ePush; }
		void onHandle(const PackagePtr &msg) override;
		void addHandle(const std::string &cmd, const std::function<void(const PackagePtr)> &cb);
		std::vector<std::string> cmdList() const;

	private:
		std::unordered_map<std::string, std::function<void(const PackagePtr)>> data_;
	};

}


